# coding=utf-8
"""
Copyright 2019-2020 Fang Jin Biao

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

# @Time    : 2020/5/20 20:24
# @Author  : Fang Jin Biao
# @Email   : 215466914@qq.com
# @File    : auth_controller.py
# @Project : SnowAdminWeb
import datetime
import json
import uuid

from flask import Blueprint, request, session
from flask_restful import Api, Resource, marshal

from webapp import redis_client, create_token
from webapp.config import ServerConfig
from webapp.config.api_utils import get_addr
from webapp.dto_mapper import user_edit_fields
from webapp.extensions import AppException
from webapp.schema import OnlineUser, UserSchema, JwtUser
from webapp.service.monitor_service import OnlineUserService
from webapp.service.sys_service import DataService, RoleService, UserService
from webapp.tools import verify_image, decrypt_by_private_key, check_password

wx_auth_app = Blueprint('wxauth', __name__, url_prefix='/wxapi/auth')
wx_auth_api = Api(wx_auth_app)


@wx_auth_api.resource('/info')
class WxGetUserInfo(Resource):
    def get(self):
        user = session.get('user')
        if user is None:
            raise AppException("未登录或登录已过期，请重新登录！")
        curr_user = UserService.find_by_id(user_id=user["id"])
        user_dict = marshal(curr_user, user_edit_fields)
        return {'user': user_dict, 'dataScopes': [curr_user.dept_id],
                "roles": RoleService.map_to_granted_authorities(user=curr_user)}


# @csrf.exempt
@wx_auth_api.resource('/login')
class WxLogin(Resource):
    def post(self):
        # 先判断该openid 是否已经存在库中，如果存在直接返回认知成功
        data = request.get_json()
        if "uuid" not in data:
            return {'code': 1, 'message': '验证码不存在或已过期'}
        code_id = data['uuid']
        code = redis_client.get(code_id)
        if not code:
            return {'code': 1, 'message': '验证码不存在或已过期'}
        if code.lower() != data['code'].lower():
            redis_client.delete(code_id)
            return {'code': 1, 'message': '验证码错误'}
        redis_client.delete(code_id)

        openid = data['openid']
        wxlogin = UserService.checkOpenid(openid)

        # 获取用户信息
        user = UserService.find_by_name(data["username"])
        if user is None:
            return {'code': 1, 'message': '用户名或密码错误，请重新输入!'}
        # 密码解密
        password = decrypt_by_private_key(ServerConfig.rsa_private_key, data["password"])
        if not check_password(password, user.password.encode("utf-8")):
            return {'code':1,'message':'用户名或密码错误，请重新输入!'}
        browser = f'{request.user_agent.browser}({request.user_agent.version})/{request.user_agent.platform}'
        token = create_token(data["username"])
        # 如果之前登录过，而且账号密码都对那么，直接返回
        if wxlogin == None:
            # 将uid和openid存入数据库
            UserService.saveWxInfo(openid,user.user_id)
        address = get_addr(request.remote_addr)
        roles = RoleService.map_to_granted_authorities(user=user)
        online_schema = OnlineUser(id=user.user_id, username=user.username, nick_name=user.nick_name,
                                   dept=user.dept.name, browser=browser, ip=request.remote_addr, address=address,
                                   key=token)
        online_user = online_schema.to_dict()
        redis_client.set(f"{ServerConfig.online_key}{token}", json.dumps(online_user, ensure_ascii=False))
        redis_client.expire(f"{ServerConfig.online_key}{token}", ServerConfig.token_validity_in_seconds)
        user_schema = UserSchema()
        user_dict = user_schema.dump(user)
        print('online_user:', online_user)
        session["user"] = online_user
        print('session:', session['user'])
        jwt_user = JwtUser(user=user_dict, dataScopes=DataService.get_dept_ids(user=user), roles=roles)
        rs = {'token': f'{ServerConfig.token_start_with} {token}', "user": jwt_user.to_dict()}
        OnlineUserService.check_online_user(username=user.username, igore_token=token)
        return rs


@wx_auth_api.resource('/logout')
class Logout(Resource):
    def delete(self):
        # session.pop('user', None)
        token = request.headers.environ.get("HTTP_AUTHORIZATION")
        if token:
            redis_client.delete(f"{ServerConfig.online_key}{token}")
        return None, 200
